import { dictToMap, isObject, notNull, pathJoinParams } from '@/utils';
import { Tooltip } from 'antd';
import moment from 'moment';
import React, { useRef } from 'react';
import { Link } from 'react-router-dom';
import { useCall, useDictionary, useSimpleMemo } from '.';

const mapCol = (map, text, fallback = '--') => {
  const keyArray = `${text}`.split(',').filter(Boolean);

  const list = keyArray.map((key) => map?.[key] ?? (fallback === '--' ? key ?? fallback : fallback));

  return list.map((val, index) => (
    <React.Fragment key={index}>
      {val}
      {index === list.length - 1 ? '' : ', '}
    </React.Fragment>
  ));
};

function DictMapCol({ code, text, fallback }) {
  const dictMap = useDictionary(code, false, dictToMap);

  return mapCol(dictMap, text, fallback);
}

const date = (v) => moment(v).format('YYYY-MM-DD');
const datetime = (v) => moment(v).format('YYYY-MM-DD HH:mm:ss');

const formatters = {
  order: (val, row, index) => `${index + 1}`,
  date: (val) => <span style={{ fontSize: 11 }}>{date(val)}</span>,
  datetime: (val) => <span style={{ fontSize: 11 }}>{datetime(val)}</span>,
  datetimetips: (val) => <Tooltip title={datetime(val)}>{<span style={{ fontSize: 11 }}>{date(val)}</span>}</Tooltip>,
  datetimetitle: (val) => <span title={datetime(val)} style={{ fontSize: 11 }} children={date(val)} />,
  fromnow: (val) => moment(val).fromNow(),
};

const getLinkParams = (linkProps, row) => linkProps.reduce((r, k) => ({ ...r, [k]: row[k] }), {});

function renderCol0() {
  return { props: { colSpan: 0 } };
}

function mapColumn(column) {
  let {
    map,
    dict,
    format,
    link,
    linkProps = [column.dataIndex],
    render,
    tooltip,
    fallback,
    props = null,
    minWidth,
    ...others
  } = column;
  let colSpanRef = useRef(1);

  let cols = [
    {
      ...others,
      render: useCall((col, row, index) => {
        let p = props;
        if (typeof p === 'function') p = p(col, row, index);

        let el = col;
        switch (true) {
          case typeof render === 'function':
            el = render(el, row, index);
            break;

          case el == null:
            el = fallback ?? '--';
            break;

          case typeof format === 'string' && formatters.hasOwnProperty(format):
            el = formatters[format](el, row, index);
            break;

          case typeof link === 'string':
            el = <Link to={pathJoinParams(link, getLinkParams(linkProps, row))}>{col}</Link>;
            break;

          case typeof el === 'string':
            if (typeof map === 'object') el = mapCol(map, el, fallback) ?? fallback;
            if (typeof dict === 'string') el = <DictMapCol code={dict} text={el} fallback={fallback} />;
        }

        if (tooltip) {
          el = (
            <Tooltip placement='top' content={el} {...(isObject(tooltip) ? tooltip : null)}>
              {el}
            </Tooltip>
          );
        }

        return {
          children: el,
          props: {
            ...(p || null),
            colSpan: colSpanRef.current,
          },
        };
      }),
    },
  ];

  if (notNull(minWidth)) {
    const [col] = cols;

    colSpanRef.current = 2;
    cols = [
      { ...col, width: minWidth, align: col.align ?? 'left', colSpan: 2 },
      { key: `minWidth:${col.dataIndex || col.key}`, colSpan: 0, render: renderCol0 },
    ];
  } else {
    colSpanRef.current = 1;
  }
  return cols;
}

function useTableColumns(columns) {
  return useSimpleMemo(columns?.flatMap(mapColumn) ?? []);
}

export default useTableColumns;
